/*--------------------------------------------------------------
 * File: devBML12.c 编码类型：C语言  UTF-8
 * Author WRS (1352509846@qq.com)
 * 功能: 模拟的设备2(BML12)功能
 * Version 0.1
 * Date 2024-10-15 
 * 
 * @copyright Copyright (c) 2024
 * 
----------------------------------------------------------------*/
#include "devBML12.h"
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "data.h"
#include "ui.h"
#include "Dev_task.h"

extern lv_indev_t * indev_keypad;
extern lv_group_t * group_ML12;
extern const Env_ST Env_st;

// static const char *TAG = "devBML12 ";
char devBML12_Name[20] = {"BML12:   0"};
bml12_t bml12_info = {0};

TaskHandle_t devBML12_task_Handle = NULL;

/*--------------------------------------------------------------
 * 功能: 初始化bml12_info
 * 
----------------------------------------------------------------*/
void bml12_info_Init(void)
{
    NVS_data_read_blob(DEV_INFO_NAMESPACE, BML12_key, (uint8_t *)&bml12_info, sizeof(bml12_t));
    if(bml12_info.dev_flag == Info_Save)
    {
        bml12_info.devType = emTypeML12;
        bml12_info.dev_index = 0;
        bml12_info.dev_SCRindex = 0;
        bml12_info.devAddrNow = 0x00;
        // 清零 dev_AI 数组
        memset(bml12_info.dev_AI, 0, sizeof(bml12_info.dev_AI));
        // 清零 dev_DO 数组
        memset(bml12_info.dev_DO, 0, sizeof(bml12_info.dev_DO));
        return ;
    }
    
    bml12_info.devType = emTypeML12;
    bml12_info.devLEDtime = emFlashRequest;
    bml12_info.dev_num = 1;
    bml12_info.dev_index = 0;
    bml12_info.dev_SCRindex = 0;
    bml12_info.devAddrNow = 0x00;
    bml12_info.dev_state = devStart;
}

/*--------------------------------------------------------------
 * 功能: 模拟的设备1初始化
 * 
----------------------------------------------------------------*/
static esp_err_t devBML12_init(void)
{
    ui_Scr4_ML12_screen_init();
    _ui_screen_change(&ui_Scr4_ML12, LV_SCR_LOAD_ANIM_FADE_ON, 100, 0, NULL);
    lv_indev_set_group(indev_keypad, group_ML12);
    lv_group_focus_obj(ui_ML12_DpDown1);   // 默认聚焦到下拉框上
    
    return ESP_OK;
}


/*--------------------------------------------------------------
 * 功能: 模拟设备1启动
 * 
----------------------------------------------------------------*/
void devBML12_Start(void)
{
    devBML12_init();
}

/*--------------------------------------------------------------
 * 功能: 模拟设备2停止
 * 
----------------------------------------------------------------*/
void devBML12_Stop(void)
{
    if(ui_Del_Scr_timer != NULL)
    {
        lv_timer_del(ui_Del_Scr_timer);
        ui_Del_Scr_timer = NULL;
    }
    if(Led_timer != NULL)
    {
        lv_timer_del(Led_timer);
        G_LED_SET(LED_OFF);
        Led_timer = NULL;
    }
    if(ui_Scr4_ML12_timer != NULL)
    {
        lv_timer_del(ui_Scr4_ML12_timer);
        ui_Scr4_ML12_timer = NULL;
    }
    if(ui_Scr4_ML12 != NULL)
    {
        lv_obj_del(ui_Scr4_ML12);
        ui_Scr4_ML12 = NULL;
    }    
}

static void Change_Relay_BML12(uint8_t devIndex, uint8_t DOch, uint8_t val)
{
    uint8_t ch = DOch - BML12_DO_CH0; // DOx
    if(devIndex > BML12_MAX_NUM)
    {
        MY_ERROR("BML12 dev Index ERROR: %d", devIndex);
    }
    if(ch >= BML12_DOChannel)
    {
        MY_ERROR("BML12 DOch ERROR: %d", ch);
    }

    if(val == 1)
    {
        bml12_info.dev_DO[devIndex][ch] = val;
    }
    else if(val == 0)   // 关闭
    {
        bml12_info.dev_DO[devIndex][ch] = val;
    }
}

static float Get_ADCReturnValue_BML12(uint8_t devIndex, uint8_t ML12ch, uint8_t Type)
{
    float f_data = 0;

    switch (bml12_info.dev_Random_mode[devIndex])
    {
        case emRandom_0:
            f_data = 0.0;
            break;
        case emRandom_2:
            f_data = 2.0;
            break;
        case emRandom_10:
            f_data = 10.0;
            break;
        case emRandom_0_10:
            f_data = (float)(Random_data_in_range(0, 1000)) / 100.0;    // 保留两位小数
            break;
        case emRandom_2_10:
            f_data = (float)(Random_data_in_range(200, 1000)) / 100.0;    // 保留两位小数
            break; 
        case emRandom_sin:
            f_data = (float)(Random_data_in_sin(10, 50, 0));    // 振幅10，周期50Hz，相位偏移0
            break;
        case emRandom_SD:
            f_data = (float)(Random_data_in_sin(10, 50, 0));    // 振幅10，周期50Hz，相位偏移0
            break;            
        default:
            break;
    }

    return f_data;
}

/****************************************************************
 **描  述: 写入AO  DO信息
*****************************************************************/
void VARTable_RecVar_BML12(uint32_t ctrl, uint8_t *pValue, void *pVarDes)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    uint32_t u32_data;
    BitAction BitVal;
    int i;
    uint16_t PartMask;
    uint16_t PartData;
    printf("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);
    
    // 485协议
    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol == em485)
    {        
        // 写
        if (pRS485_VarCtrl_st->RWctrl == emRS485Write)
        {
            MY_DEBUG("BML12 Write 0x%02X", pRS485_VarName_st->VarName);
            u32_data = *(uint32_t *)pValue;
            BitVal = u32_data;

            if (pRS485_VarName_st->VarName >= BML12_DO_CH0 && pRS485_VarName_st->VarName < BML12_DO_END)
            {
                MY_DEBUG("DO=%X\n", BitVal);
                Change_Relay_BML12(bml12_info.dev_Addrindex, pRS485_VarName_st->VarName, BitVal);
            }
            // else if (pRS485_VarName_st->VarName == emVarDOAll && _gAlarmFlag == 0)
            else if (pRS485_VarName_st->VarName == emVarDOAll)
            {
                PartMask = u32_data >> 16;
                PartData = u32_data & 0xFFFF;
                for (i = 0; i < BML12_DOChannel; i++)
                {
                    BitVal = (PartData >> i) & 1;
                    if (((PartMask >> i) & 1) == 1)
                    {
                        Change_Relay_BML12(bml12_info.dev_Addrindex, BML12_DO_CH0 + i, BitVal);
                    }
                }
            }
            else if (pRS485_VarName_st->VarName == emVarClearAlm)
            {
                // 报警                
                if (u32_data == 1)
                {
                    for (i = 0; i < BML12_DOChannel; i++)
                    {
                        // 设置报警模式时开灯，取消报警模式时无动作
                        Change_Relay_BML12(bml12_info.dev_Addrindex, BML12_DO_CH0 + i, u32_data);
                    }
                }
                else if(u32_data == 0)
                {
                    for (i = 0; i < BML12_DOChannel; i++)
                    {
                        // 设置报警模式时开灯，取消报警模式时无动作
                        Change_Relay_BML12(bml12_info.dev_Addrindex, BML12_DO_CH0 + i, u32_data);
                    }
                }
            }
        }
    }
}

uint32_t VARTable_RecVarR_BML12(uint32_t ctrl, uint8_t *pValue, void *pVarDes, uint8_t *devaddr)
{
    struct RS485_VarCtrl_ST *pRS485_VarCtrl_st = (struct RS485_VarCtrl_ST *)&ctrl;
    struct LocalVarDescription_ST *pLocalVarDescription_st = (struct LocalVarDescription_ST *)pVarDes;
    struct RS485_VarName_ST *pRS485_VarName_st = (struct RS485_VarName_ST *)&pLocalVarDescription_st->var_name;
    uint32_t u32_data = 0;
    // uint8_t VarData[128];
    uint16_t PartData;
    // float f_data = 0.0;
    int i;
    struct SemVer_ST Version;

    printf("VarName=%X,%X,%X,COM=%d\n", pRS485_VarName_st->VarName, pLocalVarDescription_st->var_length, pLocalVarDescription_st->VType_un.VarType, pRS485_VarCtrl_st->COMx);

    if (Env_st.COMSet_st[pRS485_VarCtrl_st->COMx].protocol != em485)
        return 0;
    
    *devaddr = bml12_info.devAddr[bml12_info.dev_Addrindex];

    // 485协议
    if (pRS485_VarName_st->VarName >= BML12_DI_CH0 && pRS485_VarName_st->VarName < BML12_DI_END)
    {
        // 读取DI
        // u32_data = 1 - gpio_input_bit_get(DI_PORT[pRS485_VarName_st->VarName - BML12_DI_CH0], DI_PIN[pRS485_VarName_st->VarName - BML12_DI_CH0]);
    }
    else if (pRS485_VarName_st->VarName >= BML12_AI_CH0 && pRS485_VarName_st->VarName < BML12_AI_END)
    {
        // 读取AI
        MY_DEBUG("read AI %d ", pRS485_VarName_st->VarName);        
        bml12_info.dev_AI[bml12_info.dev_Addrindex][pRS485_VarName_st->VarName-BML12_AI_CH0] = Get_ADCReturnValue_BML12(bml12_info.dev_Addrindex, pRS485_VarName_st->VarName-BML12_AI_CH0,0);
        memcpy(pValue, &bml12_info.dev_AI[bml12_info.dev_Addrindex][pRS485_VarName_st->VarName-BML12_AI_CH0], 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName >= BML12_DO_CH0 && pRS485_VarName_st->VarName < BML12_DO_END)
    {
        // 读取单路DO
        // 读取DO设定值，并不一定是真实值
        u32_data = bml12_info.dev_DO[bml12_info.dev_Addrindex][pRS485_VarName_st->VarName - BML12_DO_CH0];
        // memcpy(&u32_data, &u32_data, 4);
    }
    else if (pRS485_VarName_st->VarName == emVarDIAll)
    {
        // 读取所有DI
        PartData = 0;
        u32_data = 0;
        for (i = 0; i < BML12_DIChannel; i++)
        {
            // PartData = 1 - gpio_input_bit_get(DI_PORT[i], DI_PIN[i]);
            u32_data |= PartData << i;
            u32_data |= 1 << (i + 16);
        }
    }
    else if (pRS485_VarName_st->VarName == emVarDOAll)
    {
        // 读取所有DO，0x20
        for (i = 0; i < BML12_DOChannel; i++)
        {
            u32_data |= bml12_info.dev_DO[bml12_info.dev_Addrindex][i] << i;
            u32_data |= 1 << (i + 16);
        }
    }
    else if (pRS485_VarName_st->VarName == emVarAIAll)
    {
        // 读取所有的AI
        for (i = 0; i < BML12_AIChannel; i++)
        {
            bml12_info.dev_AI[bml12_info.dev_Addrindex][i] = Get_ADCReturnValue_BML12(0, i + BML12_AI_CH0, 0);
            memcpy(pValue, &bml12_info.dev_AI[bml12_info.dev_Addrindex][i], 4);
            pValue += 4;
        }
        return BML12_AIChannel * 4;
    }
    else if (pRS485_VarName_st->VarName == emVarClearAlm)
    {
        // 读取报警信息
        // u32_data = _gAlarmFlag;
    }
    else if (pRS485_VarName_st->VarName == emVarCPUID)
    {
        // 读取CPUID
        // memcpy(pValue, &mcu_id, 16);
        return 16;
    }
    else if (pRS485_VarName_st->VarName == emVarVer)
    {
        // 读取版本号
        Version = Env_st.Version;
        memcpy(pValue, &Version, 4);
        return 4;
    }
    else if (pRS485_VarName_st->VarName == emVarName)
    {
        // 读取名称
        memcpy(pValue, &Env_st.Dev_Name, 16);
        return 16;
    }
    else if (pRS485_VarName_st->VarName == emVarAddr)
    {
        // 读取地址
        u32_data = bml12_info.devAddr[bml12_info.dev_Addrindex];
    }
    else
    {
        return 0;
    }
    memcpy(pValue, &u32_data, 4);
    return 4;
}







